import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoClient {
    // Socket 客户端和服务器都会使用，通过 socket 进行数据传输.
    // 此处针对一个客户端提供具体的服务（读写数据）
    private Socket socket = null;

    public TcpEchoClient(String serverIp, int serverPort) throws IOException {
        // 客户端在 new socket 时，就会和服务器建立TCP连接，此时需要服务器IP和端口号
        socket = new Socket(serverIp,serverPort);
    }

    public void start(){
        System.out.println("client start!"); 
        // TCP 是面向字节流的 使用InputStream/OutputStream，socket就是一个"文件"
        try(InputStream inputStream = socket.getInputStream(); //返回此套接字的输入流
            OutputStream outputStream = socket.getOutputStream()) { //返回此套接字的输出流
            Scanner scanner = new Scanner(System.in);

            Scanner scannerNetwork = new Scanner(inputStream);
            PrintWriter writer = new PrintWriter(outputStream);

            while(true){
                // 1. 从控制台读取用户输入
                System.out.print("-> ");
                String request = scanner.next();
                // 2. 把请求发送给服务器
                // 注意：此处没有 XXXPacket 这样的类表示传输的基本单位. TCP传输的基本单位是字节(byte)
                // PrintWriter这个类内置了缓冲区，即只是把数据先放进缓冲区（本质上是一段内存空间）了，缓冲区满了，才会真正统一写入到IO设备里
                // 因为在进行IO的过程中，操作硬盘、网卡、打印机，都属于"低效操作"（和内存比），要尽可能减少访问这些慢速设备的次数
                writer.println(request);
                writer.flush(); // flush 冲刷缓冲区，即使缓冲区没满，也能真正写入
                // 3. 从服务器读取响应
                if(!scannerNetwork.hasNext()){
                    break;
                }
                String response = scannerNetwork.next();
                // 4. 把响应显示到控制台上
                System.out.println(response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        TcpEchoClient client = new TcpEchoClient("127.0.0.1",9090);
        client.start();
    }
}
